package cn.zn.modules.money.bigdata.controller;

import cn.hutool.core.util.NumberUtil;
import cn.zn.framework.common.utils.ResultBaiduSugar;
import cn.zn.modules.money.cur.entity.vo.MoneyCateMainNameSumVO;
import cn.zn.modules.money.cur.entity.vo.MoneySumVO;
import cn.zn.modules.money.cur.service.TMoneyInfoService;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("money/bigdata")
@Api(tags = "经费大屏接口")
public class MoneyBigdataController {

    @Autowired
    private TMoneyInfoService tMoneyInfoService;

    @PostMapping("/availableTotal")
    @ApiOperation("经费剩余")
    public ResultBaiduSugar availableTotal() {
        List<MoneySumVO> moneySumVOS = tMoneyInfoService.querySum().stream().filter(o -> !o.getMoneyTypeCode().equals("003")).collect(Collectors.toList());
        return ResultBaiduSugar.ok().put("data", moneySumVOS.stream().mapToDouble(o -> (o.getTotalMoney() == null ? 0 : o.getTotalMoney()) - (o.getFreezeMoney() == null ? 0 : o.getFreezeMoney()) - (o.getUseMoney() == null ? 0 : o.getUseMoney())).sum());
    }

    @PostMapping("/sumTotal")
    @ApiOperation("经费汇总")
    public ResultBaiduSugar sumTotal() {
        List<MoneySumVO> moneySumVOS = tMoneyInfoService.querySum().stream().filter(o -> !o.getMoneyTypeCode().equals("003")).collect(Collectors.toList());
        List<Double> totals = Lists.newArrayList();
        List<Double> uses = Lists.newArrayList();
        List<Double> availables = Lists.newArrayList();
        moneySumVOS.forEach(o -> {
            double total = o.getTotalMoney() == null ? 0 : o.getTotalMoney();
            double freeze = o.getFreezeMoney() == null ? 0 : o.getFreezeMoney();
            double use = o.getUseMoney() == null ? 0 : o.getUseMoney();
            totals.add(total);
            uses.add(NumberUtil.add(freeze, use));
            availables.add(NumberUtil.sub(total, NumberUtil.add(freeze, use)));
        });
        Map<String, Object> data = Maps.newHashMap();
        data.put("columns", Lists.newArrayList(this.getColumnMap("title", "名称"), this.getColumnMap("val", "值")));
        data.put("rows", Lists.newArrayList(this.getRowMap("总额", totals), this.getRowMap("已用", uses), this.getRowMap("余额", availables)));
        return ResultBaiduSugar.ok().put("data", data);
    }

    @PostMapping("/sumItemTotal")
    @ApiOperation("经济分类汇总")
    public ResultBaiduSugar sumItemTotal() {
        List<MoneyCateMainNameSumVO> moneyCateMainNameSumVOS = tMoneyInfoService.querySumForCateMainAll();
        List<String> categories = Lists.newArrayList();
        List<Double> uses = Lists.newArrayList();
        List<Double> availables = Lists.newArrayList();
        moneyCateMainNameSumVOS.forEach(o -> {
            categories.add(o.getCateNameMain().concat("(").concat(o.getCateCodeMain()).concat(")"));
            double total = o.getTotalMoney() == null ? 0 : o.getTotalMoney();
            double freeze = o.getFreezeMoney() == null ? 0 : o.getFreezeMoney();
            double use = o.getUseMoney() == null ? 0 : o.getUseMoney();
            double useRate = total == 0 ? 0 : NumberUtil.div(NumberUtil.add(freeze, use), total, 2);
            double availableRate = total == 0 ? 0 : NumberUtil.sub(1, useRate);
            uses.add(useRate);
            availables.add(availableRate);
        });
        Map<String, Object> data = Maps.newHashMap();
        data.put("categories", categories);
        data.put("series", Lists.newArrayList(this.getSeriesMap("已用", uses), this.getSeriesMap("剩余", availables)));
        return ResultBaiduSugar.ok().put("data", data);
    }

    @PostMapping("/useRate")
    @ApiOperation("经费使用率")
    public ResultBaiduSugar useRate() {
        List<MoneySumVO> moneySumVOS = tMoneyInfoService.querySum().stream().filter(o -> !o.getMoneyTypeCode().equals("003")).collect(Collectors.toList());
        List<Double> totals = Lists.newArrayList();
        List<Double> uses = Lists.newArrayList();
        moneySumVOS.forEach(o -> {
            double total = o.getTotalMoney() == null ? 0 : o.getTotalMoney();
            double freeze = o.getFreezeMoney() == null ? 0 : o.getFreezeMoney();
            double use = o.getUseMoney() == null ? 0 : o.getUseMoney();
            totals.add(total);
            uses.add(NumberUtil.add(freeze, use));
        });
        Double totalAll = totals.stream().mapToDouble(o -> o).sum();
        Double useAll = uses.stream().mapToDouble(o -> o).sum();
        Map<String, Object> data = Maps.newHashMap();
        data.put("max", 100);
        data.put("min", 0);
        data.put("name", "财政预算");
        data.put("unit", "%");
        data.put("value", NumberUtil.compare(totalAll, 0) == 0 ? 0 : NumberUtil.div(useAll, totalAll, 2) * 100);
        data.put("hideName", false);
        return ResultBaiduSugar.ok().put("data", data);
    }

    /**
     * 得到列表头
     *
     * @param id
     * @param name
     * @return
     */
    private Map<String, Object> getColumnMap(String id, String name) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("id", id);
        map.put("name", name);
        return map;
    }

    /**
     * 得到列表数据
     *
     * @param title
     * @param vals
     * @return
     */
    private Map<String, Object> getRowMap(String title, List<Double> vals) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("title", title);
        map.put("val", NumberUtil.add(vals.toArray(new Double[0])));
        return map;
    }

    /**
     * 得到柱状图数据
     *
     * @param title
     * @param vals
     * @return
     */
    private Map<String, Object> getSeriesMap(String title, List<Double> vals) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("name", title);
        map.put("data", vals);
        return map;
    }
}
